﻿using System;
using System.Collections.Generic;
using System.Text;
using Animals.Model;
using Dogs.Model;
using Dogs.Business;
using System.Collections;

namespace Dogs.Controller
{
    class AnimalFacadeImpl:AnimalFacade
    {

        private IdGenerator _idGenerator;


        public AnimalFacadeImpl()
        {
            _idGenerator = new IdGenerator();
        }

        public Animal AddOrUpdateAnimal(Animal animal, bool isNewAnimal)
        {
            if (isNewAnimal)
            {
                return AddAnimal(animal.Name, animal.BirthDate, animal.Gender, animal.Parents.FatherId, animal.Parents.MotherId);
            }
            else
            {
                return UpdateAnimal(animal.Id, animal.Name, animal.BirthDate, animal.Gender, animal.Parents.FatherId, animal.Parents.MotherId);
            }
        }

        public bool isEffectiveDate(DateTime date)
        {
            long CurrAnimalID = _idGenerator.GetId();

            CurrAnimalID -= 1; 
            if (date != null)
            {
                Animal effAnimal = GetAnimalById(CurrAnimalID);

                if (effAnimal != null)
                {
                    return DateUtil.IsFirstDateLater(date, effAnimal.BirthDate);
                }
            }

            return false;                         
        }

        public Animal AddAnimal(string Name, DateTime BirthDate, bool Gender, long FatherId, long MotherId)
        {
            long id = _idGenerator.GetNewId();
            
            ParentsPair parents = new ParentsPair(id, FatherId, MotherId);
            ParentsHolder.Parents.Add(parents);

            Animal animal = new Animal(id, Name, BirthDate, Gender, parents);
            AnimalsHolder.Animals.Add(animal);

            CreateAnimalsAndParents();

            return animal;
        }

        public Animal UpdateAnimal(Animal animal)
        {
            Animal animalUpdated = GetAnimalById(animal.Id);
            int index = AnimalsHolder.Animals.IndexOf(animalUpdated);
            AnimalsHolder.Animals.RemoveAt(index);
            return AddOrUpdateAnimal(animal, false);
        }

        public Animal UpdateAnimal(long id, string Name, DateTime BirthDate, bool Gender, long FatherId, long MotherId)
        {
            ParentsPair parents = new ParentsPair(id, FatherId, MotherId);

            Animal animal = new Animal(id, Name, BirthDate, Gender, parents);

            UpdateAnimalInParents(id);

            ParentsHolder.Parents.Add(parents);
            AnimalsHolder.Animals.Add(animal);

            CreateAnimalsAndParents();

            return animal;
        }

        private void UpdateAnimalInParents(long animalId)
        {
            foreach (ParentsPair parents in new ArrayList(ParentsHolder.Parents))
           // foreach (ParentsPair parents in ParentsHolder.Parents)
            {
                if (animalId == parents.AnimalId/* || animalId == parents.FatherId || animalId == parents.MotherId*/)
                {
                    int index = ParentsHolder.Parents.IndexOf(parents);
                    ParentsHolder.Parents.RemoveAt(index);
                }
                else if (animalId == parents.FatherId)
                {
                    Animal animalLocal = GetAnimalById(parents.AnimalId);
                    animalLocal.Parents.FatherId = parents.FatherId;
                    UpdateAnimal(animalLocal);
                    // UpdateAnimal(animalLocal.Id, animalLocal.Name, animalLocal.BirthDate, animalLocal.Gender, -1, animalLocal.Parents.MotherId);
                }
                else if (animalId == parents.MotherId)
                {
                    Animal animalLocal = GetAnimalById(parents.AnimalId);
                    animalLocal.Parents.MotherId = parents.MotherId;
                    UpdateAnimal(animalLocal);
                    // UpdateAnimal(animalLocal.Id, animalLocal.Name, animalLocal.BirthDate, animalLocal.Gender, animalLocal.Parents.FatherId, -1);
                }
            }
        }

        public void DeleteAnimal(long id)
        {
            Animal animal = GetAnimalById(id);
            int index = AnimalsHolder.Animals.IndexOf(animal);
            AnimalsHolder.Animals.RemoveAt(index);
            Serializator.CreateAnimals(AnimalsHolder.Animals);
            DeleteAnimalFromParents(animal);
        }

        private void DeleteAnimalFromParents(Animal animal)
        {
            foreach (ParentsPair parents in ParentsHolder.Parents)
            {
                if (animal.Id == parents.AnimalId)
                {
                    int index = ParentsHolder.Parents.IndexOf(parents);
                    ParentsHolder.Parents.RemoveAt(index);
                    CreateAnimalsAndParents();
                }
                else if (animal.Id == parents.FatherId)
                {
                    Animal animalLocal = GetAnimalById(parents.AnimalId);
                    UpdateAnimal(animalLocal.Id, animalLocal.Name, animalLocal.BirthDate, animalLocal.Gender, -1, animalLocal.Parents.MotherId);
                    CreateAnimalsAndParents();
                }
                else if (animal.Id == parents.MotherId)
                {
                    Animal animalLocal = GetAnimalById(parents.AnimalId);
                    UpdateAnimal(animalLocal.Id, animalLocal.Name, animalLocal.BirthDate, animalLocal.Gender, animalLocal.Parents.FatherId, -1);
                    CreateAnimalsAndParents();
                }
            }

        }

        private void CreateAnimalsAndParents()
        {
            Serializator.CreateAnimals(AnimalsHolder.Animals);
            Serializator.CreateParents(ParentsHolder.Parents);
        }

        public SortedDictionary<long, string> GetAllAnimals()
        {
            SortedDictionary<long, string> idNameAnimals = new SortedDictionary<long, string>();
            foreach(Animal animal in AnimalsHolder.Animals)
            {
                idNameAnimals.Add(animal.Id, animal.Name);
            }
            return idNameAnimals;
        }

        public SortedDictionary<long, string> GetAllMaleAnimals()
        {
            SortedDictionary<long, string> idNameAnimals = new SortedDictionary<long, string>();
            foreach (Animal animal in AnimalsHolder.Animals)
            {
                if (animal.Gender)
                {
                    idNameAnimals.Add(animal.Id, animal.Name);
                }
            }
            return idNameAnimals;
        }

        public SortedDictionary<long, string> GetAllFemaleAnimals()
        {
            SortedDictionary<long, string> idNameAnimals = new SortedDictionary<long, string>();
            foreach (Animal animal in AnimalsHolder.Animals)
            {
                if (!animal.Gender)
                {
                    idNameAnimals.Add(animal.Id, animal.Name);
                }
            }
            return idNameAnimals;
        }

        public SortedDictionary<long, string> GetAnimalsByDate(DateTime BirthDate) 
        {
            SortedDictionary<long, string> idNameAnimals = new SortedDictionary<long, string>();
            foreach (Animal animal in AnimalsHolder.Animals)
            {
                if(DateUtil.IsDateEqual(animal.BirthDate, BirthDate))
                {
                    idNameAnimals.Add(animal.Id, animal.Name);
                }
            }
            return idNameAnimals;
        }

        public Animal GetAnimalById(long Id)
        {
            foreach (Animal animal in AnimalsHolder.Animals)
            {
                if (animal.Id.Equals(Id))
                {
                    return animal;
                }
            }
            return null;
        }

        public ParentsPair GetParentsById(long Id)
        {
            foreach (ParentsPair parents in ParentsHolder.Parents)
            {
                if (parents.AnimalId.Equals(Id))
                {
                    return parents;
                }
            }
            return null;
        }
    }
}
